/******************************************************************************
 * SAGE - Scalable Adaptive Graphics Environment
 *
 * Module: sageDisplay.h
 * Author : Byungil Jeong, Rajvikram Singh
 *
 *	Description:	This is the header file for the video display module of SAGE. 
 *
 *	Notes	: 	Since the display window may receive its many pieces from many servers, we need to pass multiple buffers
 *			to this class. Each of the buffers passed contains a frame which forms a part (or whole) of the image on
 *			the display side.
 *
 * Copyright (C) 2007 Electronic Visualization Laboratory,
 * University of Illinois at Chicago
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either Version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser Public License along
 * with this library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * Direct questions, comments etc about SAGE to bijeong@evl.uic.edu or 
 * http://www.evl.uic.edu/cavern/forum/
 *			
***************************************************************************************************************************/

#ifndef SAGE_DISPLAY_H
#define SAGE_DISPLAY_H

#if defined(__APPLE__)
#include <ApplicationServices/ApplicationServices.h>
#include <AGL/agl.h>
#include <OpenGL/OpenGL.h>

#else

#include <SDL/SDL.h>

#endif


#include "sageSync.h"
#include "sage.h"
#include "sageDraw.h"
#include "sageCircBuf.h"


#if defined(__APPLE__)
#include <OpenGL/gl.h>	// Header File For The OpenGL Library
#include <OpenGL/glu.h>	// Header File For The GLu Library
#else
#include <GL/gl.h>	   // Header File For The OpenGL Library
#include <GL/glu.h>	   // Header File For The GLu Library
#include <GL/glext.h>  // Header File For The OpenGL Extensions
#endif





#define MAX_MONTAGE_NUM 	100

struct sageDisplayConfig{
	int 	width;
	int 	height;
	int	dimX;
	int	dimY;
	sageRect	tileRect[MAX_TILES_PER_NODE];

	int	mullionX;
	int	mullionY;
	int	xpos;
	int	ypos;
	int	red, green, blue;
	
	bool	fullScreenFlag;
};

// The following structure holds the parameters of the montage comprising the final window
class sageMontage : public sageRect {
private:
	GLint 	glInternalFormat;
	GLenum 	glFormat, glType;
	float		bytesPerPixel;
	int		texWidth, texHeight;		// current texture size for this montage
	int		offsetX, offsetY;			// offsets for loading pixel blocks to texture
	int		margin;
	sageRect imgInfo;
	
	GLubyte *texture;

	int initPixelType(sagePixFmt pixelT);
		
public:
	int 		texHandle;
	sageRect texCoord;
	sagePixFmt pixelType;
	float 	depth;
	int		monIdx;
	int		tileIdx;
	bool		visible;
	
	sageMontage() : texWidth(0), texHeight(0), offsetX(0), offsetY(0), texture(NULL),
			texHandle(-1), depth(1.0), monIdx(0), tileIdx(0), visible(true) {}
	
	int init(sageBlock *block);
	int copyConfig(sageMontage &mon);		
	int renewTexture();
	int deleteTexture();
	int genTexCoord(int offsetX, int offsetY);
	int loadPixelBlock(sageBlock *block);  // load a pixel block into texture memory		
};


#if defined(__APPLE__)

// Shared AGL pixel format and context:
extern AGLPixelFormat agl_fmt;
extern AGLContext agl_ctx;


///////////////////////////
// Define a playback window
class Window {

public:

  Window(const Rect & rect, int fulls);

  ~Window() {
    aglDestroyContext(m_ctx);
    DisposeWindow(m_win);
  }

  void clear() {
    aglSetCurrentContext(m_ctx);

    glClearColor(0,0,0,1);
    glClear(GL_COLOR_BUFFER_BIT);

    glFlush();

    aglSwapBuffers(m_ctx);
  }

  void clearOpenGLData() {
    m_init = false;
  }

  WindowRef theWindow() {
    return m_win;
  }

  void beginGL() {
    aglSetCurrentContext(m_ctx);
    glClear(GL_COLOR_BUFFER_BIT);
  }

  void endGL() {
    glFlush();
    aglSwapBuffers(m_ctx);
  }

protected:

  // Carbon API window reference:
  WindowRef m_win;

  // Window geometry:
  Rect m_rect;

  // OpenGL context:
  AGLContext m_ctx;

  // OpenGL data:
  bool m_init;
};

// The windows
extern Window *windows[MAX_TILES_PER_NODE];

// Critical section object:
extern MPCriticalRegionID cr;

#endif

class sageDisplay{
private:
	sageDisplayConfig *configStruct;
	bool					winCreatFlag;
	sageMontage* 		montages[MAX_TILES_PER_NODE][MAX_MONTAGE_NUM];
    
    int take_snapshot;
    unsigned char *snapshot_dump;
    int snapshot_counter;
    
	int noOfMontages[MAX_TILES_PER_NODE];
	int tileNum;
	
	sageDraw drawObj;
	
public:
	sageDisplay() : winCreatFlag(false) {}
	int init(struct sageDisplayConfig*);	
	int addMontage(sageMontage *mon);  // register a new montage into the montage list
	int replaceMontage(sageMontage *mon); // replace the current montage by another montage
	int removeMontage(sageMontage *mon);  // delete montage from the montage list
	int updateScreen();  					// draw montages onto screen
	int changeBGColor(int red, int green, int blue);
	int takeSnapshot();

	int addDrawObjectInstance(char *data);
	int updateObjectPosition(char *data);
	int removeDrawObject(char *data);
	int forwardObjectMessage(char *data);
	
	~sageDisplay();
};

#endif
